﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using CommandLine;
using Yahoo.Yui.Compressor;

namespace JSBuild
{
    public class Program
    {
        private static Options opts = new Options();
        private static StringBuilder output = new StringBuilder();
        private static TextWriter logfile;
        public static Version Version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;

        static void Main(string[] args)
        {
            CommandLineParser parser = new CommandLineParser();
            String name = String.Empty;
            if (parser.ParseArguments(args, opts))
            {

                if (opts.LogFile != null)
                {
                    logfile = new StreamWriter(opts.LogFile);
                }
                
                if (opts.Verbose)
                {
                    name = "ConCatJS " + Version.ToString() + " (Verbose Mode)";
                }
                else
                {
                    name = "ConCatJS " + Version.ToString() + " (Quiet Mode)";
                }

                WriteOutput(name + Environment.NewLine);

                // Make sure we got a recognized file type.
                if (opts.Type != "js" && opts.Type != "css")
                {
                    WriteOutput("Unrecognized file type '" + opts.Type + "'");
                }

                if (opts.Verbose)
                {
                    for (int i = 1; i <= name.Length; i++)
                    {
                        WriteOutput("-");
                    }
                    WriteOutput(Environment.NewLine + Environment.NewLine);
                }

                // Process all the files we should be processing.
                Process(opts.Source);

                if (opts.Verbose)
                {
                    WriteOutput(Environment.NewLine + "Output:" + Environment.NewLine + Environment.NewLine);
                    WriteOutput(output.ToString().Trim());
                }
                
                DumpFile();
                
                if (logfile != null)
                {
                    logfile.Close();
                }
            }
            else
            {
                Console.Error.Write(opts.GetUsage());
            }
        }

        private static void Process(String path)
        {
            if (opts.Verbose)
            {
                WriteOutput("Processing: " + path + " ..." + Environment.NewLine);
            }
            String[] files = Directory.GetFiles(path);
            String fileContents = String.Empty;
            foreach (String file in files)
            {
                fileContents = String.Empty;
                if (file.EndsWith(opts.Extension))
                {
                    if (opts.Verbose)
                    {
                        WriteOutput("Processing: " + file + " ..." + Environment.NewLine);
                    }
                    // Make sure there actually is something in the file before we write it to the output.
                    fileContents = System.IO.File.ReadAllText(file).Trim();
                    if (fileContents != String.Empty)
                    {
                        output.AppendLine("/*");
                        output.AppendLine(" * " + file);
                        output.AppendLine(" */");
                        output.AppendLine("");
                        output.Append(fileContents);
                        output.AppendLine("");
                        output.AppendLine("");
                    }
                    else
                    {
                        WriteOutput("Skipping file with no content:   " + file + " ..." + Environment.NewLine);
                    }
                }
                else
                {
                    if (opts.Verbose)
                    {
                        WriteOutput("Skipping:   " + file + " ..." + Environment.NewLine);
                    }
                }
            }
            String[] directories = Directory.GetDirectories(path);
            foreach (String directory in directories)
            {
                Process(directory);
            }
        }

        private static void DumpFile()
        {
            // Write the compiled output to a file.
            TextWriter tw = new StreamWriter(opts.Output);
            tw.Write(AddWarningMessage());
            tw.Write(output.ToString().Trim());
            tw.Close();
            WriteOutput(" - Done creating " + opts.Output + Environment.NewLine);

            // Write the minified if asked to do so.
            if (opts.MinifiedOutput != null)
            {
                TextWriter mtw = new StreamWriter(opts.MinifiedOutput);
                mtw.Write(AddWarningMessage());
                if (opts.Type == "js")
                {
                    mtw.Write(JavaScriptCompressor.Compress(output.ToString().Trim()));
                }
                if (opts.Type == "css")
                {
                    mtw.Write(CssCompressor.Compress(output.ToString().Trim()));
                }
                mtw.Close();
                WriteOutput(" - Done creating " + opts.MinifiedOutput + Environment.NewLine);
            }
        }

        private static StringBuilder AddWarningMessage()
        {
            StringBuilder output = new StringBuilder();
            output.AppendLine("/*");
            output.AppendLine(" * *** NOTICE: DO NOT EDIT THIS FILE - GENERATED BY ConCatJS ***");
            output.AppendLine(" */");
            return output;
        }

        private static void WriteOutput(String output)
        {
            if (opts.LogFile != null)
            {
                logfile.Write(output);
            }
            else
            {
                Console.Write(output);
            }
        }
    }
}
